﻿// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone

using BlazorAdmin.Caching;
using BlazorAdmin.Extensions;
using BlazorAdmin.Models;
using BlazorAdmin.Interface;
using System;
using System.Collections.Generic;
using System.Linq;
using BlazorAdmin.Services.DbService;

namespace BlazorAdmin.Services
{
    internal class RoleService : BaMgmtDbService, IRole
    {
        private const string RoleServiceGetAllCacheKey = "RoleService-GetAll";
        private const string RoleServiceGetRolesByUserIdCacheKey = "RoleService-GetRolesByUserId";
        private const string RoleServiceGetRolesByGroupIdCacheKey = "RoleService-GetRolesByGroupId";
        private const string RoleServiceGetRolesByMenuIdCacheKey = "RoleService-GetRolesByMenusId";

        /// <summary>
        /// 
        /// </summary>
        /// <param name="db"></param>
        public RoleService(IPetaPoco db) : base(db)
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public List<Role> GetAll() => CacheManager.GetOrAdd(RoleServiceGetAllCacheKey, entry => CacheManager.GetOrAdd(RoleServiceGetAllCacheKey, entry => Fetch<Role>()));

        public List<int> GetRolesByGroupId(int groupId) =>
            CacheManager.GetOrAdd($"{RoleServiceGetRolesByGroupIdCacheKey}-{groupId}",
            entry => Fetch<int>("SELECT RoleID FROM RoleGroup WHERE GroupID = @0", groupId));

        public List<int> GetRolesByUserId(int userId) => CacheManager.GetOrAdd($"{RoleServiceGetRolesByUserIdCacheKey}-{userId}",
            entry => Fetch<int>("SELECT RoleID FROM UserRole WHERE UserID = @0", userId));

        public List<int> GetRolesByMenuId(int menuId) => CacheManager.GetOrAdd($"{RoleServiceGetRolesByMenuIdCacheKey}-{menuId}",
            entry => Fetch<int>("SELECT RoleID FROM NavigationRole WHERE NavigationID = @0", menuId));

        /// <summary>
        /// 
        /// </summary>
        /// <param name="groupId"></param>
        /// <param name="roleIds"></param>
        /// <returns></returns>
        public bool SaveRolesByGroupId(int groupId, IEnumerable<int> roleIds)
        {
            var ret = false;
            using var db = Create();
            try
            {
                db.BeginTransaction();
                db.Execute("DELETE FROM RoleGroup WHERE GroupID = @0", groupId);
                db.InsertBatch("RoleGroup", roleIds.Select(g => new { RoleID = g, GroupID = groupId }));
                db.CompleteTransaction();
                ret = true;
            }
            catch (Exception)
            {
                db.AbortTransaction();
                throw;
            }
            if (ret)
            {
                CacheManager.Clear();
            }
            return ret;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="roleIds"></param>
        /// <returns></returns>
        public bool SaveRolesByUserId(int userId, IEnumerable<int> roleIds)
        {
            var ret = false;
            using var db = Create();
            try
            {
                db.BeginTransaction();
                db.Execute("DELETE FROM UserRole WHERE UserID = @0", userId);
                db.InsertBatch("UserRole", roleIds.Select(g => new { RoleID = g, UserID = userId }));
                db.CompleteTransaction();
                ret = true;
            }
            catch (Exception)
            {
                db.AbortTransaction();
                throw;
            }
            if (ret)
            {
                CacheManager.Clear();
            }
            return ret;
        }

        public bool SaveRolesByMenuId(int menuId, IEnumerable<int> roleIds)
        {
            var ret = false;
            using var db = Create();
            try
            {
                db.BeginTransaction();
                db.Execute("DELETE FROM NavigationRole WHERE NavigationID = @0", menuId);
                db.InsertBatch("NavigationRole", roleIds.Select(g => new { RoleID = g, NavigationID = menuId }));
                db.CompleteTransaction();
                ret = true;
            }
            catch (Exception)
            {
                db.AbortTransaction();
                throw;
            }
            if (ret)
            {
                CacheManager.Clear();
            }
            return ret;
        }
    }
}